package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.Player;
import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.*;

import java.util.*;

/**
 * 俄罗斯方块棋
 */
public class TetrisRoom extends Room {

    public static final int PENALTY_SCORE = 9;//触顶扣分
    public static final String BORDER_COLOR = ColorCost.TABLECLOTH_COLOR;
    public String gameMessage = "";
    private static final String TEXT_COLOR = "#EEFFFF00";
    private int[][] currentCurgrids = new int[20][20];//当前的棋盘，因不用棋子用sign表示棋子，所以要重建一个棋盘存储信息
    private boolean startGame = false;
    private int[][] theLastPosition = new int[4][2];


    public TetrisRoom(String roomName) {
        super(roomName, "\t\t俄罗斯方块棋，目前处于测试中。", "俄罗斯方块棋", BoardStyleData.getGoBangStyle(20, 20), true, true);
        blackScore = 0;
        whiteScore = 0;
        cacheSign = new CacheSign(this, "TBG", 1, true, getBackground());
    }

    int currentPositionX = 0;//当前需要落在的位置左上角的横坐标
    int currentPositionY = 0;//当前需要落在的位置的纵坐标

    private CacheSign cacheSign;//缓存地图
    private String waitList;//等待队列，落地之后会去掉，由字母S,Z,L,T,I,J组成
    int[][] curentShape;//目前第一个块的状态

    List<Sign> upList = new ArrayList<Sign>();
    boolean InAnimation = false;
    private static final Map<Character, int[][]> charToMatrixMap = new HashMap<>();//列举其中字母代表的形状

    private int[][] eightPosition = new int[][]{
            {1, 11}, {1, 16},
            {6, 11}, {6, 16},
            {11, 11}, {11, 16},
            {16, 11}, {16, 16},
    };

    static {
        charToMatrixMap.put('L', new int[][]{
                {0, 1, 0, 0},
                {0, 1, 0, 0},
                {0, 1, 1, 0},
                {0, 0, 0, 0}});
        charToMatrixMap.put('J', new int[][]{
                {0, 0, 1, 0},
                {0, 0, 1, 0},
                {0, 1, 1, 0},
                {0, 0, 0, 0}});
        charToMatrixMap.put('I', new int[][]{
                {0, 0, 1, 0},
                {0, 0, 1, 0},
                {0, 0, 1, 0},
                {0, 0, 1, 0}});
        charToMatrixMap.put('O', new int[][]{
                {0, 0, 0, 0},
                {0, 1, 1, 0},
                {0, 1, 1, 0},
                {0, 0, 0, 0}});
        charToMatrixMap.put('Z', new int[][]{
                {0, 0, 0, 0},
                {1, 1, 0, 0},
                {0, 1, 1, 0},
                {0, 0, 0, 0}});
        charToMatrixMap.put('S', new int[][]{
                {0, 0, 0, 0},
                {0, 0, 1, 1},
                {0, 1, 1, 0},
                {0, 0, 0, 0}});
        charToMatrixMap.put('T', new int[][]{
                {0, 0, 0, 0},
                {0, 1, 1, 1},
                {0, 0, 1, 0},
                {0, 0, 0, 0}});
    }

    private boolean canLeftOrRight(int a) {
        if (a == 0) {
            if (currentPositionY > 0) {
                return true;
            } else if (currentPositionY == 0) {
                for (int j = 0; j < 4; j++) {
                    if (curentShape[j][0] != 0) {
                        return false;
                    }
                }
                return true;
            } else if (currentPositionY == -1) {
                for (int i = 0; i < 4; i++) {
                    if (curentShape[i][1] != 0) {
                        return false;
                    }
                }
                return true;
            } else if (currentPositionY == -2) {
                for (int i = 0; i < 4; i++) {
                    if (curentShape[i][2] != 0) {
                        return false;
                    }
                }
                return true;
            }
        } else if (a == 1) {
            if (currentPositionY < 6) {
                return true;
            } else if (currentPositionY == 6) {

                for (int j = 0; j < 4; j++) {
                    if (curentShape[j][3] != 0) {
                        return false;
                    }
                }
                return true;
            } else if (currentPositionY == 7) {
                for (int i = 0; i < 4; i++) {
                    if (curentShape[i][2] != 0) {
                        return false;
                    }
                }
                return true;
            } else if (currentPositionY == 8) {
                for (int i = 0; i < 4; i++) {
                    if (curentShape[i][1] != 0) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    private void clearTmp() {
        for (int i = 0; i < currentCurgrids.length; i++) {
            for (int j = 0; j < 10; j++) {
                if (currentCurgrids[i][j] == 3 || currentCurgrids[i][j] == 4)
                    currentCurgrids[i][j] = 0;
            }
        }
    }

    CustomBottom btn_Left = new CustomBottom(this, "左移", p -> {
        clearTmp();
        if (canLeftOrRight(0))
            currentPositionY--;
        noticeAllRefreshGameInfo();
    });
    CustomBottom btn_Right = new CustomBottom(this, "右移", p -> {
        clearTmp();
        if (canLeftOrRight(1))
            currentPositionY++;
        noticeAllRefreshGameInfo();
    });
    //    CustomBottom btn_Anticlockwise = new CustomBottom(this, "左旋", p -> {
//        clearTmp();
//        rotate90CounterClockwise(curentShape);
//        noticeAllRefreshGameInfo();
//    });
    CustomBottom btn_Rotate = new CustomBottom(this, "旋转", p -> {
        clearTmp();
        rotate90Clockwise(curentShape);
        noticeAllRefreshGameInfo();
    });
    CustomBottom btn_Fall = new CustomBottom(this, "落下", p -> {
        if (!InAnimation) {
            int k = 5;
            for (int i = 0; i < 20; i++) {
                for (int j = 0; j < 10; j++) {
                    if (currentCurgrids[i][j] == 3 || currentCurgrids[i][j] == 4) {
                        k = currentCurgrids[i][j];
                        break;
                    }
                }
            }
            stepAdd();
            makeSure(k);
            List<Integer> fullLines = getCheckLine();
            if (!fullLines.isEmpty()) {//检查是否构成一行,若构成就额外获得一步
                noticeAllRefreshGameInfo();
                InAnimation = true;
                List<Integer> indexes = new ArrayList<Integer>();
                List<Integer> blackIndexes = new ArrayList<Integer>();
                List<Integer> whiteIndexes = new ArrayList<Integer>();
                Timer timer = new Timer();

                // 第一秒执行的任务
                TimerTask task1 = new TimerTask() {
                    @Override
                    public void run() {

                        for (int i = 0; i < fullLines.size(); i++) {
                            for (int j = 0; j < 10; j++) {
                                Integer in = getIndex(fullLines.get(i), j);
                                indexes.add(in);
                                if (currentCurgrids[fullLines.get(i)][j] == 1) {
                                    blackIndexes.add(in);
                                } else if (currentCurgrids[fullLines.get(i)][j] == 2) {
                                    whiteIndexes.add(in);
                                }

                            }
                        }
                        upList.add(new AroundSign(indexes, "#00110011", "#FF00FF00", 1f));
                        noticeAllRefreshGameInfo();
                    }
                };
                timer.schedule(task1, 600);
                TimerTask task2 = new TimerTask() {
                    @Override
                    public void run() {
                        if (cur == 1 && !blackIndexes.isEmpty()) {
                            upList.add(new AroundSign(blackIndexes, "#00110011", "#AA00AA00", 1f));
                            blackScore += blackIndexes.size();
                        } else if (cur == 2 && !whiteIndexes.isEmpty()) {
                            upList.add(new AroundSign(whiteIndexes, "#00110011", "#AA00AA00", 1f));
                            whiteScore += whiteIndexes.size();
                        }
                        for (int i = 0; i < fullLines.size(); i++) {
                            for (int j = 0; j < 10; j++) {
                                if (currentCurgrids[fullLines.get(i)][j] == cur) {
                                    currentCurgrids[fullLines.get(i)][j] = 0;
                                }
                            }
                        }
                        gameMessage = (cur == 1 ? "黑方获得" + blackIndexes.size() + "分" : "白方获得" + whiteIndexes.size() + "分");
                        noticeAllRefreshGameInfo();
//                        for (int i = 0; i < fullLines.size(); i++) {
//                            for (int j = 0; j < 10; j++) {
//
//                            }
//                        }
                        System.out.println("第一秒执行的操作");
                    }
                };
                timer.schedule(task2, 1200);

                // 第二秒执行的任务
                TimerTask task3 = new TimerTask() {
                    @Override
                    public void run() {
                        if (cur == 2 && !blackIndexes.isEmpty()) {
                            upList.add(new AroundSign(blackIndexes, "#00110011", "#AA00AA00", 1f));
                            blackScore += blackIndexes.size();
                        } else if (cur == 1 && !whiteIndexes.isEmpty()) {
                            upList.add(new AroundSign(whiteIndexes, "#00110011", "#AA00AA00", 1f));
                            whiteScore += whiteIndexes.size();
                        }
                        for (int i = 0; i < fullLines.size(); i++) {
                            for (int j = 0; j < 10; j++) {
                                if (currentCurgrids[fullLines.get(i)][j] == (cur == 1 ? 2 : 1)) {
                                    currentCurgrids[fullLines.get(i)][j] = 0;
                                }
                            }
                        }
                        gameMessage = (cur == 1 ? "白方获得" + whiteIndexes.size() + "分" : "黑方获得" + blackIndexes.size() + "分");
                        noticeAllRefreshGameInfo();
                        System.out.println("第二秒执行的操作");
                    }
                };
                timer.schedule(task3, 1800);

                // 第三秒执行的任务
                TimerTask task4 = new TimerTask() {
                    @Override
                    public void run() {

                        for (int i = 0; i < fullLines.size(); i++) {
                            for (int j = fullLines.get(i); j > 0; j--) {
                                for (int l = 0; l < 10; l++) {
                                    currentCurgrids[j][l] = currentCurgrids[j - 1][l];
                                }
                            }
                        }
                        InAnimation = false;
                        if (!checkWin()) {
                            stillMove();
                        } else {
                            return;
                        }
                        System.out.println("第三秒执行的操作");

                    }
                };
                timer.schedule(task4, 2400);


            } else {
                checkSpace();
                if (!checkWin()) {
                    changeMove();
                } else {
//                    end();
                    return;
                }
            }
        }
    });

    // 逆时针旋转 90°
    public void rotate90CounterClockwise(int[][] matrix) {
        int n = matrix.length;
        int[][] rotated = new int[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rotated[n - 1 - j][i] = matrix[i][j];
            }
        }
        // 将旋转后的矩阵复制回原矩阵
        for (int i = 0; i < n; i++) {
            System.arraycopy(rotated[i], 0, matrix[i], 0, n);
        }
        //需要重新判断横坐标
    }

    private void resetPositionY() {
        if (currentPositionY == -3) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][2] != 0) {
                    currentPositionY++;
                    break;
                }
            }
        }
        if (currentPositionY == -2) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][1] != 0) {
                    currentPositionY++;
                    break;
                }
            }
        }
        if (currentPositionY == -1) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][0] != 0) {
                    currentPositionY++;
                    break;
                }
            }
        }
        if (currentPositionY == 9) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][1] != 0) {
                    currentPositionY--;
                    break;
                }
            }
        }
        if (currentPositionY == 8) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][2] != 0) {
                    currentPositionY--;
                    break;
                }
            }
        }
        if (currentPositionY == 7) {
            for (int i = 0; i < 4; i++) {
                if (curentShape[i][3] != 0) {
                    currentPositionY--;
                    break;
                }
            }
        }
    }

    // 顺时针旋转 90°
    public void rotate90Clockwise(int[][] matrix) {
        int n = matrix.length;
        int[][] rotated = new int[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rotated[j][n - 1 - i] = matrix[i][j];
            }
        }

        // 将旋转后的矩阵复制回原矩阵
        for (int i = 0; i < n; i++) {
            System.arraycopy(rotated[i], 0, matrix[i], 0, n);
        }

        //需要重新判断横坐标
        resetPositionY();
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        List<Sign> tmpSignList = new ArrayList<>();
        updateBoard(tmpSignList);
        return super.getGameInfo();
    }

    @Override
    protected void doStart() {
        super.doStart();
        createWaitList();
        startGame = true;
        currentCurgrids = new int[20][20];
        getButton(1);
        curentShape = getList(0);
        gameMessage = "黑方落子中···";
        noticeAllRefreshGameInfo();
    }

    @Override
    public void resetGrids() {
        startGame = false;
        waitList = "";
        currentCurgrids = new int[20][20];
        currentPositionY = 0;
        currentPositionX = 0;
        curentShape = null;
        blackScore = 0;
        whiteScore = 0;
        InAnimation = false;
        clearButtoms();
        gameMessage = "";

        super.resetGrids();
    }

    private List<Sign> getBackground() {
        List<Sign> tetris_bgd = new ArrayList<Sign>();

        //去除外边框线
        tetris_bgd.add(new GroundSign(getIndex(0, 0), getIndex(19, 19), "#00FFFFFF", BORDER_COLOR, 2f, 0, 0));

        //绘制棋盘
        tetris_bgd.add(new GroundSign(getIndex(0, 10), getIndex(19, 10), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(0, 15), getIndex(19, 15), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(0, 10), getIndex(19, 10), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(0, 10), getIndex(0, 19), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(5, 10), getIndex(5, 19), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(10, 10), getIndex(10, 19), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(15, 10), getIndex(15, 19), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));

        //画落子区域边框
        tetris_bgd.add(new GroundSign(getIndex(0, 0), getIndex(19, 9), "#00000000", "#FF000000", 2f, 0, 0));

        tetris_bgd.add(new GroundSign(getIndex(1, 11), getIndex(4, 14), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(6, 11), getIndex(9, 14), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(11, 11), getIndex(14, 14), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(16, 11), getIndex(19, 14), "#00000000", "#FF000000", 2f, 0, 0));

        tetris_bgd.add(new GroundSign(getIndex(1, 16), getIndex(4, 19), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(6, 16), getIndex(9, 19), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(11, 16), getIndex(14, 19), "#00000000", "#FF000000", 2f, 0, 0));
        tetris_bgd.add(new GroundSign(getIndex(16, 16), getIndex(19, 19), "#00000000", "#FF000000", 2f, 0, 0));

//        tetris_bgd.add(new GroundSign(getIndex(0, 20), getIndex(20, 20), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
//        tetris_bgd.add(new GroundSign(getIndex(20, 0), getIndex(20, 20), BORDER_COLOR, "#00FFFFFF", 0f, 0, 0));
        tetris_bgd.add(new TextSign(getIndex(1, 10), "   1", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(1, 15), "   2", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(6, 10), "   3", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(6, 15), "   4", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(11, 10), "   5", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(11, 15), "   6", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(16, 10), "   7", TEXT_COLOR));
        tetris_bgd.add(new TextSign(getIndex(16, 15), "   8", TEXT_COLOR));
        tetris_bgd.add(new GroundSign(getIndex(0, 0), getIndex(0, 9), "#80F0F08C", "#00FFDD00", 0f, 0, 0)); //警告区域背景颜色
        tetris_bgd.add(new TitleSign(0.25f, 0.015f, 0, "Warning!!!!", "#FFFF4040", 1f));
        return tetris_bgd;
    }

    private void updateBoard(List<Sign> tmpSignList) {
        signList.clear(); //清除旧记号
        signList.add(cacheSign);
        for (int i = 0; i < 20; i++) {
            for (int j = 10; j < 20; j++) {
                currentCurgrids[i][j] = 0;
            }
        }
        //绘制预加载队列
        if (startGame) {

            for (int i = 0; i < (Math.min(waitList.length(), 8)); i++) {
                int[] aPosition = eightPosition[i];
                if (getList(i) != null) {
                    for (int j = 0; j < curentShape.length; j++) {
                        for (int k = 0; k < curentShape[0].length; k++) {
                            int xPosition = aPosition[0] + j;
                            int yPosition = aPosition[1] + k;
                            if (i == 0)
                                currentCurgrids[xPosition][yPosition] = curentShape[j][k];
                            else
                                currentCurgrids[xPosition][yPosition] = getList(i)[j][k];
                        }
                    }
                }
            }
            for (int i = 0; i < 20; i++) {
                for (int j = 10; j < 20; j++) {
                    if (currentCurgrids[i][j] == 1) {
                        if (j > 9 && j < 15 && i > 0 && i < 5) {
                            currentCurgrids[i][j] = cur;
                        } else {
                            currentCurgrids[i][j] = 5;
                        }
                    }
                }
            }
            if (curentShape != null) {

                resetPositionY();
                //确认可下降最小位置 在这一段似乎有bug，不知道怎么改
                clearTmp();
                int[] maxHeight = new int[4];
                int min = 19;
                boolean[] whatNull = new boolean[4];
                int[] minhigh = new int[4];
                for (int i = 0; i < 4; i++) {
                    boolean isNull = true;
                    for (int j = 0; j < 4; j++) {
                        if (curentShape[j][i] != 0) {
                            isNull = false;
                            minhigh[i] = j;
                        }
                    }
                    whatNull[i] = isNull;
                }
                for (int i = 0; i < 20; i++) {
                    for (int j = 0; j < 4; j++) {
                        if (!whatNull[j]) {
                            if (j + currentPositionY < 0 || j + currentPositionY > 9) {

                            } else if (currentCurgrids[i][j + currentPositionY] > 0) {
                                maxHeight[j] = i;
                                if (i < min)
                                    min = i;
                            }
                        }
                    }
                }
                currentPositionX = min - 4;

                if (curentShape != null) {

                    while (true) {
                        if (isNotOverflow()) {
                            if (isOverlap()) {
                                break;
                            }
                        } else {
                            break;
                        }
                        currentPositionX++;
                    }
                    currentPositionX--;
                    //不要问下面这个是干嘛的，反正不加这个就是会有bug
                    if (currentPositionX <= 0) {

                        while (true) {
                            boolean xx = false;
                            for (int i = 0; i < 4; i++) {
                                if (!whatNull[i]) {
                                    if (currentPositionX + minhigh[i] + 1 >= 0 && currentPositionX + minhigh[i] + 1 < 20)
                                        if (currentCurgrids[currentPositionX + minhigh[i] + 1][currentPositionY + i] != 0) {
                                            xx = true;
                                            break;
                                        }
                                }
                            }
                            if (!xx) {
                                currentPositionX++;
                            } else {
                                break;
                            }
                        }
                    }
//            int[] maxHigh = new int[4];
                    //处理特殊情况

                    //这个b特殊情况处理不好啊
                    //将该位置投影到棋盘
                    //投影到棋盘的位置currentCurgrids[currentPositionX+i][currentPositionY+j]
                    //自身的位置currentList[i][j]
                    for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                            if (curentShape[i][j] != 0) {
                                if (currentPositionX + i >= 0 && currentPositionX + i <= 19 && currentPositionY + j >= 0 && currentPositionY + j <= 9)
                                    currentCurgrids[currentPositionX + i][currentPositionY + j] = (cur == 1 ? 3 : 4);
                            }
                        }
                    }
                }
            }
        }
        List<Integer> blackSquare = new ArrayList<Integer>();
        List<Integer> whiteSquare = new ArrayList<Integer>();
        List<Integer> whiteTmpSquare = new ArrayList<Integer>();
        List<Integer> blackTmpSquare = new ArrayList<Integer>();
        List<Integer> waitSquare = new ArrayList<Integer>();
        for (int i = 0; i < currentCurgrids.length; i++) {
            for (int j = 0; j < currentCurgrids[0].length; j++) {
                if (currentCurgrids[i][j] == 1) {
                    blackSquare.add(getIndex(i, j));
                } else if (currentCurgrids[i][j] == 2) {
                    whiteSquare.add(getIndex(i, j));
                } else if (currentCurgrids[i][j] == 3) {
                    blackTmpSquare.add(getIndex(i, j));
                } else if (currentCurgrids[i][j] == 4) {
                    whiteTmpSquare.add(getIndex(i, j));
                } else if (currentCurgrids[i][j] == 5) {
                    waitSquare.add(getIndex(i, j));
                }
            }
        }


        if (!blackSquare.isEmpty())
            tmpSignList.add(new AroundSign(blackSquare, "#EEEE0000", "#00000000", 1f)); //完成落子后的黑方颜色 and 预览区域的颜色
        if (!whiteSquare.isEmpty())
            tmpSignList.add(new AroundSign(whiteSquare, "#EE0000EE", "#00000000", 1f)); //完成落子后的白方颜色
        if (!blackTmpSquare.isEmpty())
            tmpSignList.add(new AroundSign(blackTmpSquare, "#33EE0000", "#00000000", 1f)); //当前待选预览棋子颜色
        if (!whiteTmpSquare.isEmpty())
            tmpSignList.add(new AroundSign(whiteTmpSquare, "#330000EE", "#00000000", 1f)); //当前待选预览棋子颜色
        if (!waitSquare.isEmpty())
            tmpSignList.add(new AroundSign(waitSquare, "#EEEEEE00", "#00000000", 1f)); //右边等待列表棋子颜色

        //文字提示区
        tmpSignList.add(new TitleSign(0.75f, 0.017f, 0, gameMessage, "#EEFF4040", 0.9f));


        //添加上步落子提示
        if (step != 0 && startGame && theLastPosition != null) {
            List<Integer> indexes = new ArrayList<Integer>();
            for (int i = 0; i < 4; i++) {
                indexes.add(getIndex(theLastPosition[i][0], theLastPosition[i][1]));
            }
            tmpSignList.add(new AroundSign(indexes, "#00000000", "#FF00EE00", 1f));  //上步落子提示颜色
            theLastPosition = null;
        }
        if (!tmpSignList.isEmpty())
            signList.addAll(tmpSignList);
        if (!upList.isEmpty())
            signList.addAll(upList);
        upList.clear();

    }

    private boolean isOverlap() {//是否重叠
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if ((currentPositionY + j) >= 0 && (currentPositionY + j) <= 9 && (currentPositionX + i) >= 0 && (currentPositionX + i) <= 19)
                    if (curentShape[i][j] != 0 && currentCurgrids[currentPositionX + i][currentPositionY + j] != 0) {
                        return true;
                    }
            }
        }
        return false;
    }

    private boolean isNotOverflow() {//确认是否没有越界

//        int minHigh = 114514;
//        for (int i = 3; i >= 0; i--) {
//            for (int j = 0; j < 4; j++) {
//                if (curentShape[i][j] != 0) {
//                    minHigh = i;
//                    break;
//                }
//            }
//            if (minHigh != 114514) {
//                break;
//            }
//        }
//        if (minHigh + currentPositionY >= 0) {
//            return true;
//        } else {
//            return false;
//        }
        //
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                //currentPositionX+i][currentPositionY+j

                if (curentShape[i][j] != 0) {
                    if (
                            (currentPositionX + i < 0) ||
                                    (currentPositionX + i > 19) ||
                                    (currentPositionY + j < 0) ||
                                    (currentPositionY + j > 9))
                        return false;
                }
            }
        }
        return true;
    }

    //    public static void addArrayToMatrix(int[] a, int[][] b) {
//        // 遍历二维数组的每一行
//        for (int i = 0; i < b.length; i++) {
//            // 遍历每一行的每个元素
//            for (int j = 0; j < b[i].length; j++) {
//                // 确保不会因为数组a的长度不足而出错
//                if (j < a.length) {
//                    // 给b的当前元素增加a中对应索引位置的值
//                    b[i][j] += a[j];
//                }
//            }
//        }
//    }
    @Override
    public String getRuleText() {
        return "《俄罗斯方块棋》 \n" +
                " \n" +
                "一、基本规则 \n" +
                "棋盘大小为横10格，竖20格 \n" +
                "游戏中，轮流按照俄罗斯方块的规则落下合法的方块。 \n" +
                "在对局前，生成一个方块序列用作对弈，七种方块各10枚\n" +
                "*相同方块至少隔2个其他方块后，才会再次出现相同的方块\n" +
                "（逆界版：直接隐藏方块序列，只显示下8个方块）\n" +
                " \n" +
                "二、屋檐空间惩罚 \n" +
                "当一方落下方块后，如使棋盘上出现新的屋檐空间，1格空间会给对方加2分,2格及以上空间会给对方加4分\n" +
                "*屋檐空间：空格的上方被刚落下的方块遮挡 \n" +
                "*屋檐空间的结算顺序在最后 \n" +
                " \n" +
                "三、消除得分 \n" +
                "当一方行动后形成完整的横行，则自动按照俄罗斯方块的规则进行消除（消除横条行，并将上方所有空格下移<已消除横条行数量>格），消除的每个棋子都会为棋子的所属方增加1分 \n" +
                "*形成横条得分的一方，免除该步的屋檐空间惩罚，并获得一次额外的行动 \n" +
                " \n" +
                "四、胜负 \n" +
                "出现以下情形，结算分数，分高的一方获胜\n" +
                "1、双方分差达到20分\n" +
                "2、方块序列用光\n" +
                "3、一方落子触碰顶行时（惩罚：触顶一方先扣9分再结算）";
    }

    @Override
    public void doRule(int row, int col, int value) {
        //
        if (row < 20 && col < 20) {

            if (!InAnimation) {

                int k = currentCurgrids[row][col];
                if (!(k == 3 || k == 4))
                    return;
                stepAdd();
                makeSure(k);
                List<Integer> fullLines = getCheckLine();
                if (!fullLines.isEmpty()) {//检查是否构成一行,若构成就额外获得一步
                    noticeAllRefreshGameInfo();
                    InAnimation = true;

                    List<Integer> indexes = new ArrayList<Integer>();
                    List<Integer> blackIndexes = new ArrayList<Integer>();
                    List<Integer> whiteIndexes = new ArrayList<Integer>();
                    Timer timer = new Timer();

                    // 第一秒执行的任务
                    TimerTask task1 = new TimerTask() {
                        @Override
                        public void run() {

                            for (int i = 0; i < fullLines.size(); i++) {
                                for (int j = 0; j < 10; j++) {
                                    Integer in = getIndex(fullLines.get(i), j);
                                    indexes.add(in);
                                    if (currentCurgrids[fullLines.get(i)][j] == 1) {
                                        blackIndexes.add(in);
                                    } else if (currentCurgrids[fullLines.get(i)][j] == 2) {
                                        whiteIndexes.add(in);
                                    }

                                }
                            }
                            upList.add(new AroundSign(indexes, "#00110011", "#FF00FF00", 1f));
                            noticeAllRefreshGameInfo();
                        }
                    };
                    timer.schedule(task1, 600);
                    TimerTask task2 = new TimerTask() {
                        @Override
                        public void run() {
                            if (cur == 1 && !blackIndexes.isEmpty()) {
                                upList.add(new AroundSign(blackIndexes, "#00110011", "#AA00AA00", 1f));
                                blackScore += blackIndexes.size();
                            } else if (cur == 2 && !whiteIndexes.isEmpty()) {
                                upList.add(new AroundSign(whiteIndexes, "#00110011", "#AA00AA00", 1f));
                                whiteScore += whiteIndexes.size();
                            }
                            for (int i = 0; i < fullLines.size(); i++) {
                                for (int j = 0; j < 10; j++) {
                                    if (currentCurgrids[fullLines.get(i)][j] == cur) {
                                        currentCurgrids[fullLines.get(i)][j] = 0;
                                    }
                                }
                            }
                            gameMessage = (cur == 1 ? "黑方获得" + blackIndexes.size() + "分" : "白方获得" + whiteIndexes.size() + "分");

                            noticeAllRefreshGameInfo();
//                        for (int i = 0; i < fullLines.size(); i++) {
//                            for (int j = 0; j < 10; j++) {
//
//                            }
//                        }
                            System.out.println("第一秒执行的操作");
                        }
                    };
                    timer.schedule(task2, 1200);

                    // 第二秒执行的任务
                    TimerTask task3 = new TimerTask() {
                        @Override
                        public void run() {
                            if (cur == 2 && !blackIndexes.isEmpty()) {
                                upList.add(new AroundSign(blackIndexes, "#00110011", "#AA00AA00", 1f));
                                blackScore += blackIndexes.size();
                            } else if (cur == 1 && !whiteIndexes.isEmpty()) {
                                upList.add(new AroundSign(whiteIndexes, "#00110011", "#AA00AA00", 1f));
                                whiteScore += whiteIndexes.size();
                            }
                            for (int i = 0; i < fullLines.size(); i++) {
                                for (int j = 0; j < 10; j++) {
                                    if (currentCurgrids[fullLines.get(i)][j] == (cur == 1 ? 2 : 1)) {
                                        currentCurgrids[fullLines.get(i)][j] = 0;
                                    }
                                }
                            }
                            gameMessage = (cur == 1 ? "白方获得" + whiteIndexes.size() + "分" : "黑方获得" + blackIndexes.size() + "分");
                            noticeAllRefreshGameInfo();
                            System.out.println("第二秒执行的操作");
                        }
                    };
                    timer.schedule(task3, 1800);

                    // 第三秒执行的任务
                    TimerTask task4 = new TimerTask() {
                        @Override
                        public void run() {

                            for (int i = 0; i < fullLines.size(); i++) {
                                for (int j = fullLines.get(i); j > 0; j--) {
                                    for (int l = 0; l < 10; l++) {
                                        currentCurgrids[j][l] = currentCurgrids[j - 1][l];
                                    }
                                }
                            }

                            InAnimation = false;
                            if (!checkWin()) {
                                stillMove();
                            } else {
                                return;
                            }
                            System.out.println("第三秒执行的操作");

                        }
                    };
                    timer.schedule(task4, 2400);


                } else {
                    checkSpace();
                    if (!checkWin()) {
                        changeMove();
                    } else {
//                    end();
                        return;
                    }
                }
            }
        }

    }

    private boolean checkWin() {
        if (blackScore - whiteScore >= 20) {
            clearButtoms();
            doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "战胜" + player_white.getNickNameOrTemp());
            return true;
        } else if (whiteScore - blackScore >= 20) {
            clearButtoms();
            doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "战胜" + player_black.getNickNameOrTemp());
            return true;
        } else {
            for (int i = 0; i < 9; i++) {
                if (currentCurgrids[0][i] == 1) {
                    blackScore -= PENALTY_SCORE;
                    if (blackScore > whiteScore) {
                        clearButtoms();
                        doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "战胜" + player_white.getNickNameOrTemp());
                        return true;
                    } else if (blackScore < whiteScore) {
                        clearButtoms();
                        doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "战胜" + player_black.getNickNameOrTemp());
                        return true;
                    } else {
                        clearButtoms();
                        doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "战平" + player_white.getNickNameOrTemp());
                        return true;
                    }
                } else if (currentCurgrids[0][i] == 2) {
                    whiteScore -= PENALTY_SCORE;
                    if (blackScore > whiteScore) {
                        clearButtoms();
                        doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "战胜" + player_white.getNickNameOrTemp());
                        return true;
                    } else if (blackScore < whiteScore) {
                        clearButtoms();
                        doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "战胜" + player_black.getNickNameOrTemp());
                        return true;
                    } else {
                        clearButtoms();
                        doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "战平" + player_white.getNickNameOrTemp());
                        return true;
                    }
                }
            }
        }
        if (waitList.isEmpty()) {
            if (blackScore > whiteScore) {
                clearButtoms();
                doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "战胜" + player_white.getNickNameOrTemp());
                return true;
            } else if (blackScore < whiteScore) {
                clearButtoms();
                doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "战胜" + player_black.getNickNameOrTemp());
                return true;
            } else {
                clearButtoms();
                doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "战平" + player_white.getNickNameOrTemp());
                return true;
            }
        }
        return false;
    }

    private void checkSpace() {
        int maxScoreIncrease = 0; // 用于记录每个位置可能的最大分数增加

        for (int[] a : theLastPosition) {
            int localScoreIncrease = 0; // 本次循环可能的分数增加

            if (a[0] + 1 < 20 && currentCurgrids[a[0] + 1][a[1]] == 0) { // 检查下一行同一列是否为空
                localScoreIncrease += 2; // 如果下一行为空，增加2分

                if (a[0] + 2 < 20 && currentCurgrids[a[0] + 2][a[1]] == 0) { // 再检查下下行同一列是否为空
                    localScoreIncrease += 2; // 如果下下行也为空，额外增加2分，总共4分
                }
            }

            // 更新最大分数增加
            if (localScoreIncrease > maxScoreIncrease) {
                maxScoreIncrease = localScoreIncrease;
            }
        }

        // 根据当前玩家（cur变量）增加对应的分数
        if (cur == 1) {
            whiteScore += maxScoreIncrease;
        } else {
            blackScore += maxScoreIncrease;
        }
    }

//    private void checkSpace() {
//        for (int[] a : theLastPosition) {
//            if (a[0] + 1 < 20) {
//                if (currentCurgrids[a[0] + 1][a[1]] == 0) {
//                    if (cur == 1) {
//                        whiteScore += 2;
//                        if (a[0]+2 < 20)
//                            if (currentCurgrids[a[0] + 2][a[1]] == 0)
//                                whiteScore+=2;
//                        break;
//                    } else {
//                        blackScore += 2;
//                        if (a[0]+2 < 20)
//                            if (currentCurgrids[a[0] + 2][a[1]] == 0)
//                                blackScore+=2;
//                        break;
//                    }
//                }
//            }
//        }
//    }

    public void stillMove() {
//            clearBottoms();
        if (cur == 1) {
            gameMessage = "黑方落子中···";
            noticeBlackMove();
        } else if (cur == 2) {
            gameMessage = "白方落子中···";
            noticeWhiteMove();
        }
    }

    private void getButton(int k) {
        if (k == 1) {
            player_black.registerCustomBottom(btn_Left);
            player_black.registerCustomBottom(btn_Right);
            player_black.registerCustomBottom(btn_Rotate);
            player_black.registerCustomBottom(btn_Fall);
        } else {
            player_white.registerCustomBottom(btn_Left);
            player_white.registerCustomBottom(btn_Right);
            player_white.registerCustomBottom(btn_Rotate);
            player_white.registerCustomBottom(btn_Fall);
        }

    }

    private void changeMove() {
        clearButtoms();
        if (cur == 1) {
            getButton(2);
            gameMessage = "白方落子中···";
            noticeWhiteMove();
        } else if (cur == 2) {
            getButton(1);
            gameMessage = "黑方落子中···";
            noticeBlackMove();
        }
    }


    private void clearButtoms() {
        if (player_black != null) {
            if (player_black.findCustomBottomByTitle(this, "左移") != null
                    || player_black.findCustomBottomByTitle(this, "右移") != null
                    || player_black.findCustomBottomByTitle(this, "旋转") != null
                    || player_black.findCustomBottomByTitle(this, "落下") != null) {
                player_black.clearCustomBottom();
                player_black.dispatchCustomBottom();
            }
        }
        if (player_white != null) {
            if (player_white.findCustomBottomByTitle(this, "左移") != null
                    || player_white.findCustomBottomByTitle(this, "右移") != null
                    || player_white.findCustomBottomByTitle(this, "旋转") != null
                    || player_white.findCustomBottomByTitle(this, "落下") != null) {
                player_white.clearCustomBottom();
                player_white.dispatchCustomBottom();
            }
        }
    }

    private boolean checkLine() {//检查是否构成一行
        boolean haveLine = false;
        for (int i = 0; i < 20; i++) {
            boolean isLine = true;
            for (int j = 0; j < 10; j++) {
                if (currentCurgrids[i][j] == 0) {
                    isLine = false;
                    break;
                }
            }
            if (isLine) {
                deleteLine(i);//清除一行并加分
                //i--;
                haveLine = true;
            }
        }
        return haveLine;
    }

    private List<Integer> getCheckLine() {//返回消除的行数
        List<Integer> fullLines = new ArrayList<Integer>();
//        boolean haveLine = false;
        for (int i = 0; i < 20; i++) {
            boolean isLine = true;
            for (int j = 0; j < 10; j++) {
                if (currentCurgrids[i][j] == 0) {
                    isLine = false;
                    break;
                }
            }
            if (isLine) {
                fullLines.add(i);//清除一行并加分
                //i--;
//                haveLine = true;
            }
        }
        return fullLines;
    }

    private void deleteLine(int k) {//清除一行并加分
        int blackNum = 0, whiteNum = 0;

        for (int i = 0; i < 10; i++) {
            if (currentCurgrids[k][i] == 1) {
                blackNum++;
            } else if (currentCurgrids[k][i] == 2) {
                whiteNum++;
            }
        }
        //清除一行
        for (int i = k; i > 0; i--) {
            for (int j = 0; j < 10; j++) {
                currentCurgrids[i][j] = currentCurgrids[i - 1][j];
            }
        }
        blackScore += blackNum;
        whiteScore += whiteNum;
    }

    private void makeSure(int k) {//预览位置确定为落子
        int n = 0;
        theLastPosition = new int[4][2];
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 10; j++) {
                if (currentCurgrids[i][j] == k) {
                    currentCurgrids[i][j] = cur;
                    theLastPosition[n][0] = i;
                    theLastPosition[n][1] = j;
                    n++;
                }
            }
        }
        waitList = waitList.substring(1);
        curentShape = getList(0);
    }

    private void createWaitList() {
        waitList = generateRandomString();
    }

    private int[][] getList(int i) {
        if (i < waitList.length()) {

            char s = waitList.charAt(i);
            int[][] arr1 = charToMatrixMap.get(s);
            int[][] arr2 = new int[4][4];
            for (int k = 0; k < 4; k++) {
                for (int j = 0; j < 4; j++) {
                    arr2[k][j] = arr1[k][j];
                }
            }
            return arr2;
        } else {
            return null;
        }
    }


    public static String generateRandomString() {
        // 字符和初始次数
        char[] characters = {'L', 'J', 'I', 'O', 'Z', 'S', 'T'};
        int[] counts = new int[characters.length]; // 每个字符的计数
        Arrays.fill(counts, 10);  // 每个字符可以使用10次

        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        char lastChar = ' ';
        char secondLastChar = ' ';

        while (sb.length() < 70) {
            List<Character> validChoices = new ArrayList<>();
            for (int i = 0; i < characters.length; i++) {
                if (characters[i] != lastChar && characters[i] != secondLastChar && counts[i] > 0) {
                    validChoices.add(characters[i]);
                }
            }

            if (validChoices.isEmpty()) {
                // 如果没有有效选择，重置字符串并重新开始
                sb.setLength(0);
                Arrays.fill(counts, 10);
                lastChar = ' ';
                secondLastChar = ' ';
                continue;
            }

            // 随机选择一个有效的字符
            char selected = validChoices.get(random.nextInt(validChoices.size()));
            sb.append(selected);

            // 更新使用次数
            for (int i = 0; i < characters.length; i++) {
                if (characters[i] == selected) {
                    counts[i]--;
                    break;
                }
            }

            // 更新最后两个字符
            secondLastChar = lastChar;
            lastChar = selected;
        }

        return sb.toString();
    }
//    private static String generateRandomString() {
//        // 初始字符串，每个字母出现8次
//        StringBuilder sb = new StringBuilder();
//        for (char letter : new char[]{'L', 'J', 'I', 'O', 'Z', 'S', 'T'}) {
//            for (int i = 0; i < 10; i++) {
//                sb.append(letter);
//            }
//        }
//
//        // Fisher-Yates 洗牌算法
//        Random rand = new Random();
//        while (!isValidShuffle(sb.toString())) {
//            for (int i = sb.length() - 1; i > 0; i--) {
//                int index = rand.nextInt(i + 1);
//                // 交换
//                char a = sb.charAt(index);
//                sb.setCharAt(index, sb.charAt(i));
//                sb.setCharAt(i, a);
//            }
//        }
//
//        return sb.toString();
//    }
//
//    // 检查字符串是否符合条件
//    private static boolean isValidShuffle(String str) {
//        for (int i = 0; i < str.length() - 2; i++) {
//            if (str.charAt(i) == str.charAt(i + 1) || str.charAt(i) == str.charAt(i + 2)) {
//                return false;
//            }
//        }
//        return true;
//    }

    @Override
    public String getCoordMode() {
        return "4100000A";
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return cacheSign;
    }

    @Override
    public void setBlackPlayer(Player player) {
        super.setBlackPlayer(player);
        if (overFlag == 1) { //对弈中状态
            if (player_white != null) {
                if (cur == 1) {
                    getButton(1);
                } else {
                    getButton(2);
                }
            }
        }
    }

    @Override
    public void setWhitePlayer(Player player) {

        super.setWhitePlayer(player);
        if (overFlag == 1) { //对弈中状态
            if (player_white != null) {
                if (cur == 1) {
                    getButton(1);
                } else {
                    getButton(2);
                }
            }
        }
//        noticeAllRefreshGameInfo();
    }

    @Override
    public void playerLeaveSeat(Player player) {
        clearButtoms();
        super.playerLeaveSeat(player);
    }
}
